package com.project.javagobang.api;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.project.javagobang.game.MatchRequset;
import com.project.javagobang.game.MatchResponse;
import com.project.javagobang.game.Matcher;
import com.project.javagobang.game.OnlineUserManager;
import com.project.javagobang.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
@Component
//通过这个类来处理匹配功能中的websocket请求
public class MatchAPI extends TextWebSocketHandler {
    private ObjectMapper objectMapper = new ObjectMapper();
    @Autowired
    private OnlineUserManager onlineUserManager;
    @Autowired
    private Matcher matcher;
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        //玩家上线,加入到onlineUserManager中
        //1.获取到当前用户的身份信息(谁在游戏大厅中,建立连接)
        // 此处的代码，之所以能够 getAttributes，全靠了在注册 Websocket 的时候，
        // 加上的 .addInterceptors(new HttpSessionHandshakeInterceptor());
        // 这个逻辑就把 HttpSession 中的 Attribute 都给拿到 WebSocketSession 中了
        // 在 Http 登录逻辑中，往 HttpSession 中存了 User 数据：httpSession.setAttribute("user", user);
        // 此时就可以在 WebSocket Session 中把之前 HttpSession 里存的 User 对象给拿到了.
        //此处拿到的user是有可能为空的!!
        //如果用户之前压根没有通过HTTP来进行登录,直接就通过/game_hall.html这个url来访问游戏大厅页面
        //此时就会出现user为空的情况
        try {
            User user = (User) session.getAttributes().get("user");
            //2.先判定当前用户是否已经登录(或者已经在线),如果已经在线,就不能再继续后续的逻辑
            //WebSocketSession tmpSession = onlineUserManager.getFromGameHall(user.getUserId());
            if(onlineUserManager.getFromGameHall(user.getUserId()) != null
                    || onlineUserManager.getFromGameRoom(user.getUserId()) != null) {
                //当前用户已经登录
                //针对这个情况就要告知客户端,你这里重复登录了
                MatchResponse response = new MatchResponse();
                response.setOk(true);
                response.setReason("当前禁止多开");
                response.setMessage("repeatConnection");
                session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
                //此处直接关闭有些太激进了,还是返回一个特殊的message,供我们的客户端来进行处理
                //session.close();
                return;
            }

            //3.拿到了身份信息之后就可以把玩家设置成在线状态了
            onlineUserManager.enterGameHall(user.getUserId(),session);
            System.out.println("玩家 " + user.getUserName() + " 进入了游戏大厅!");
        } catch (NullPointerException e) {
            System.out.println("[MatchAPI.afterConnectionEstablished] 当前用户未登录!");
            //e.printStackTrace();
            //出现空指针异常,说明当前用户的身份信息为空,用户未登录
            //返回信息,用户尚未登录
            MatchResponse response = new MatchResponse();
            response.setOk(false);
            response.setReason("您尚未登录,不能进行后续的匹配功能!");
            session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
            /*先通过 Object Mapper 把 Match Response 对象转成 JSON 字符串，
            然后在包装上一层 Text Message，再进行传输。
            Text Message 就表示一个文本格式的 web socket 数据包。*/

        }

    }

    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        //实现处理开始匹配请求和处理停止匹配请求
        User user = (User) session.getAttributes().get("user");
        //获取到客户端给服务器发送的数据
        String payload = message.getPayload();
        MatchRequset requset = objectMapper.readValue(payload, MatchRequset.class);
        MatchResponse response = new MatchResponse();
        if (requset.getMessage().equals("startMatch")) {
            //进入匹配队列
            //TODO 先创建一个类表示匹配队列,把当前用户加进去
            matcher.add(user);
            //把玩家信息放入匹配队列之后,就可以返回一个响应给客户端了
            response.setOk(true);
            response.setMessage("startMatch");
        } else if (requset.getMessage().equals("stopMatch")) {
            //退出匹配队列
            //TODO 先创建一个类表示匹配队列,把当前用户移除
            matcher.remove(user);
            //把玩家信息放入匹配队列之后,就可以返回一个响应给客户端了
            response.setOk(true);
            response.setMessage("stopMatch");
        } else {
            //非法情况
            response.setOk(false);
            response.setReason("非法的匹配请求");
        }
        String jsonString = objectMapper.writeValueAsString(response);
        session.sendMessage(new TextMessage(jsonString));
    }

    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        //玩家下线,从onlineUserManager中删除
        try {
            User user = (User) session.getAttributes().get("user");
            WebSocketSession tmpSession = onlineUserManager.getFromGameHall(user.getUserId());
            if(tmpSession == session) {
                onlineUserManager.exitGameHall(user.getUserId());
            }
            //如果玩家正在匹配中,而websocket连接断开了,就应该移除匹配对列
            matcher.remove(user);
            //System.out.println("玩家 " + user.getUserName() + " 退出了游戏大厅!");
        } catch (NullPointerException e) {
            System.out.println("[MatchAPI.handleTransportError] 当前用户未登录!");
            //e.printStackTrace();
            //出现空指针异常,说明当前用户的身份信息为空,用户未登录
            //返回信息,用户尚未登录
            //MatchResponse response = new MatchResponse();
            //response.setOk(false);
            //response.setReason("您尚未登录,不能进行后续的匹配功能!");
            //session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        }
    }

    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        //玩家下线,从onlineUserManager中删除
        try {
            User user = (User) session.getAttributes().get("user");
            WebSocketSession tmpSession = onlineUserManager.getFromGameHall(user.getUserId());
            if(tmpSession == session) {
                onlineUserManager.exitGameHall(user.getUserId());
            }
            //如果玩家正在匹配中,而websocket连接断开了,就应该移除匹配对列
            matcher.remove(user);
            //System.out.println("玩家 " + user.getUserName() + " 退出了游戏大厅!");
        } catch (NullPointerException e) {
            System.out.println("[MatchAPI.afterConnectionClosed] 当前用户未登录!");
            //e.printStackTrace();
            //出现空指针异常,说明当前用户的身份信息为空,用户未登录
            //返回信息,用户尚未登录
            //以下代码不应该在连接关闭之后,还尝试发送消息给客户端
            //MatchResponse response = new MatchResponse();
            //response.setOk(false);
            //response.setReason("您尚未登录,不能进行后续的匹配功能!");
            //session.sendMessage(new TextMessage(objectMapper.writeValueAsString(response)));
        }
    }
}
